This analysis explores the carbon implications of different PV sustainability/circular economy designs in the context of achieving energy transition. These calculations build upon previous work that can be found in journals 13 and 17.
Attempt 1
import numpy as np
import pandas as pd
import os,sys
from pathlib import Path
import matplotlib.pyplot as plt
cwd = os.getcwd() #grabs current working directory
testfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP' / 'CarbonAnalysis')
inputfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP')
baselinesfolder = str(Path().resolve().parent.parent /'PV_ICE' / 'baselines')
supportMatfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'baselines' / 'SupportingMaterial')
carbonfolder = str(Path().resolve().parent.parent / 'PV_ICE'/ 'baselines'/ 'CarbonLayer')
altBaselinesfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'baselines' / 'Energy_CellModuleTechCompare')
energyanalysisfolder = str(Path().resolve().parent.parent / 'PV_ICE' / 'TEMP' / 'EnergyAnalysis')
if not os.path.exists(testfolder):
os.makedirs(testfolder)
from platform import python_version
print(python_version())
3.8.8
import PV_ICE
PV_ICE.__version__
'v0.2.0+530.g0fcda0e.dirty'
#https://www.learnui.design/tools/data-color-picker.html#palette
#color pallette - modify here for all graphs below
colorpalette=['#000000', #PV ICE baseline
'#595959', '#7F7F7F', '#A6A6A6', '#D9D9D9', #BAU, 4 grays, perc, shj, topcon, irena
#'#067872','#0aa39e','#09d0cd','#00ffff', #realistic cases (4) teals, perc, shj, topcon, irena
'#0579C1','#C00000','#FFC000', #extreme cases (3) long life, high eff, circular
'#6E30A0','#00B3B5','#10C483', #ambitious modules (5) high eff+ long life, 50 yr perc, recycleSi,
'#97CB3F','#FF7E00' #circular perovskite+life, circular perovkiste+ high eff
]
colormats = ['#00bfbf','#ff7f0e','#1f77be','#2ca02c','#d62728','#9467BD','#8C564B', 'black'] #colors for material plots
import matplotlib as mpl #import matplotlib
from cycler import cycler #import cycler
mpl.rcParams['axes.prop_cycle'] = cycler(color=colorpalette) #reset the default color palette of mpl
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)
plt.rcParams.update({'font.size': 14})
plt.rcParams['figure.figsize'] = (8, 6)
scennames_labels = ['PV_ICE','PERC','SHJ','TOPCon','Low\nQuality',
'Long-Lived','High Eff','Circular',
'High Eff\n+ Long-life','Long-Life\n+ Recycling',
'Recycled-Si\n+ Long-life','Circular\n+ Long-life',
'Circular\n+ High Eff'
]
scennames_labels_flat = ['PV_ICE','PERC','SHJ','TOPCon','Low Quality',
'Long-Lived','High Eff','Circular',
'High Eff + Long-life','Long-Life + Recycling',
'Recycled-Si + Long-life','Circular + Long-life',
'Circular + High Eff'
]
MATERIALS = ['glass', 'silicon', 'silver', 'aluminium_frames', 'copper', 'encapsulant', 'backsheet']
moduleFile_m = os.path.join(baselinesfolder, 'baseline_modules_mass_US.csv')
moduleFile_e = os.path.join(baselinesfolder, 'baseline_modules_energy.csv')
#load in the simulation from Energy Analysis journal
sim1 = PV_ICE.Simulation.load_Simpickle(filename=r'C:\Users\hmirletz\Documents\GitHub\PV_ICE\PV_ICE\TEMP\EnergyAnalysis\sim1.pkl')
sim1.calculateCarbonFlows()
sim1.scenario['r_PERC'].dataOut_c
sim1.scenario['r_PERC'].dataOut_m
| Area | Cumulative_Active_Area | EOL_BadStatus | EOL_Landfill0 | EOL_PATHS | EOL_PG | Effective_Capacity_[W] | Landfill_0_ProjLife | MerchantTail_Area | MerchantTail_[W] | ... | Yearly_Sum_Area_PathsBad | Yearly_Sum_Area_PathsGood | Yearly_Sum_Area_atEOL | Yearly_Sum_Power_EOLby_Degradation | Yearly_Sum_Power_EOLby_Failure | Yearly_Sum_Power_EOLby_ProjectLifetime | Yearly_Sum_Power_PathsBad | Yearly_Sum_Power_PathsGood | Yearly_Sum_Power_atEOL | irradiance_stc | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 5.237421e+06 | 5.237421e+06 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 7.520622e+08 | 0.000000e+00 | 0.0 | 0.0 | ... | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.0 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 1070.0 |
| 1 | 2.381558e+06 | 7.618978e+06 | 5.019410e-03 | 2.844333e-02 | 5.019410e-03 | 0.000000e+00 | 1.092986e+09 | 0.000000e+00 | 0.0 | 0.0 | ... | 3.346274e-02 | 0.000000e+00 | 3.346274e-02 | 0.0 | 4.769010e+00 | 0.000000e+00 | 4.769010e+00 | 0.000000e+00 | 4.769010e+00 | 1070.0 |
| 2 | 2.399211e+06 | 1.001819e+07 | 3.883317e-01 | 2.200546e+00 | 3.883317e-01 | 0.000000e+00 | 1.437059e+09 | 0.000000e+00 | 0.0 | 0.0 | ... | 2.588878e+00 | 0.000000e+00 | 2.588878e+00 | 0.0 | 3.662374e+02 | 0.000000e+00 | 3.662374e+02 | 0.000000e+00 | 3.662374e+02 | 1070.0 |
| 3 | 3.636895e+06 | 1.365505e+07 | 4.784439e+00 | 2.711182e+01 | 4.784439e+00 | 0.000000e+00 | 1.965030e+09 | 0.000000e+00 | 0.0 | 0.0 | ... | 3.189626e+01 | 0.000000e+00 | 3.189626e+01 | 0.0 | 4.481373e+03 | 0.000000e+00 | 4.481373e+03 | 0.000000e+00 | 4.481373e+03 | 1070.0 |
| 4 | 7.372109e+06 | 2.102697e+07 | 2.774546e+01 | 1.572243e+02 | 2.774546e+01 | 0.000000e+00 | 3.051979e+09 | 0.000000e+00 | 0.0 | 0.0 | ... | 1.849697e+02 | 0.000000e+00 | 1.849697e+02 | 0.0 | 2.582007e+04 | 0.000000e+00 | 2.582007e+04 | 0.000000e+00 | 2.582007e+04 | 1070.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 96 | 7.591823e+09 | 3.541404e+11 | 1.667387e+08 | 1.552650e+09 | 4.657949e+09 | 4.491210e+09 | 8.508872e+13 | 1.497070e+09 | 0.0 | 0.0 | ... | 2.223183e+08 | 4.491210e+09 | 6.210598e+09 | 0.0 | 4.896471e+10 | 1.297565e+12 | 4.896471e+10 | 9.731736e+11 | 1.346529e+12 | 1070.0 |
| 97 | 8.003568e+09 | 3.554404e+11 | 1.278019e+08 | 1.675878e+09 | 5.027633e+09 | 4.899831e+09 | 8.530804e+13 | 1.633277e+09 | 0.0 | 0.0 | ... | 1.704025e+08 | 4.899831e+09 | 6.703511e+09 | 0.0 | 3.775151e+10 | 1.415620e+12 | 3.775151e+10 | 1.061715e+12 | 1.453372e+12 | 1070.0 |
| 98 | 4.560406e+09 | 3.574687e+11 | 1.455385e+08 | 6.330470e+08 | 1.899141e+09 | 1.753602e+09 | 8.552736e+13 | 5.845342e+08 | 0.0 | 0.0 | ... | 1.940513e+08 | 1.753602e+09 | 2.532188e+09 | 0.0 | 4.301322e+10 | 5.066369e+11 | 4.301322e+10 | 3.799777e+11 | 5.496501e+11 | 1070.0 |
| 99 | 4.619609e+09 | 3.594903e+11 | 1.708910e+08 | 6.494993e+08 | 1.948498e+09 | 1.777607e+09 | 8.574668e+13 | 5.925356e+08 | 0.0 | 0.0 | ... | 2.278547e+08 | 1.777607e+09 | 2.597997e+09 | 0.0 | 5.050157e+10 | 5.135720e+11 | 5.050157e+10 | 3.851790e+11 | 5.640736e+11 | 1070.0 |
| 100 | 4.700811e+09 | 3.615007e+11 | 2.067210e+08 | 6.725818e+08 | 2.017745e+09 | 1.811024e+09 | 8.596600e+13 | 6.036748e+08 | 0.0 | 0.0 | ... | 2.756280e+08 | 1.811024e+09 | 2.690327e+09 | 0.0 | 6.103742e+10 | 5.232268e+11 | 6.103742e+10 | 3.924201e+11 | 5.842642e+11 | 1070.0 |
101 rows × 45 columns
To parallel the PV deployment, we will assume that we globally hit 100% RE in 2050 with the 75 TW of PV. As such, we need to change the future projection of marketshares of the different country grids.
One scenario with decarb grid, one scenario with decarb grid and heat
Estimating that 60-70% generation will be from Solar, 30-40% from wind, and any remainder from "other renewables"
countrygridmix = pd.read_csv(os.path.join(carbonfolder,'baseline_countrygridmix.csv'), index_col='year')
gridsources = ['Bioenergy','Hydro','Nuclear','OtherFossil','OtherRenewables','Solar','Wind']
nonRE = ['Coal','Gas','OtherFossil','Nuclear','Bioenergy']
countrygridmix.loc[2023:,:]=np.nan #delete 2023 to 2050
nonRE_search = '|'.join(nonRE) #create nonRE search
countrygridmix.loc[2050, countrygridmix.columns.str.contains(nonRE_search)] = 0.0 #set all nonRE to 0 in 2050
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Solar')] = 63.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Wind')] = 33.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('Hydro')] = 3.0
countrygridmix.loc[2050, countrygridmix.columns.str.contains('OtherRenewables')] = 1.0
#numbers derived from leading scenario electricity generation Breyer et al 2022 scenarios (EU focused)
countrygridmix_100RE2050 = countrygridmix.interpolate() #linearly interpolate between 2022 and 2050
apnd_idx = pd.RangeIndex(start=2051,stop=2101,step=1) #create temp df
apnd_df = pd.DataFrame(columns=countrygridmix_100RE2050.columns, index=apnd_idx )
countrygridmix_100RE20502100 = pd.concat([countrygridmix_100RE2050.loc[2000:],apnd_df], axis=0) #extend through 2100
countrygridmix_100RE20502100.ffill(inplace=True) #propogate 2050 values through 2100
countrygridmix_100RE20502100.loc[2050]
China_Bioenergy 0.0
China_Coal 0.0
China_Gas 0.0
China_Hydro 3.0
China_Nuclear 0.0
...
Zambia_Nuclear 0.0
Zambia_OtherFossil 0.0
Zambia_OtherRenewables 1.0
Zambia_Solar 63.0
Zambia_Wind 33.0
Name: 2050, Length: 472, dtype: float64
This is a simple projection, assumes all countries have same ratio of PV and wind (which we know can't be true). Update in future with country specific projections.
pd.read_csv(os.path.join(carbonfolder,'baseline_electricityemissionfactors.csv'), index_col=[0])
| CO2eq_gpWh_IPCC2006 | CO2eq_gpWh_ember | CO2_gpWh_EIA | CO2_gpWh_EPA | |
|---|---|---|---|---|
| Energy Source | ||||
| Bioenergy | 0.3005 | 0.230 | 0.0000 | 0.3170 |
| Coal | 0.3487 | 0.820 | 0.3215 | 0.3380 |
| Gas | 0.2291 | 0.490 | 0.1805 | 0.1810 |
| Hydro | 0.0000 | 0.024 | 0.0000 | 0.0000 |
| Nuclear | 0.0000 | 0.012 | 0.0000 | 0.0000 |
| OtherFossil | 0.2671 | 0.700 | 0.2413 | 0.0000 |
| OtherRenewables | 0.0000 | 0.038 | 0.0000 | 0.0000 |
| Solar | 0.0000 | 0.048 | 0.0000 | 0.0000 |
| Wind | 0.0000 | 0.011 | 0.0000 | 0.0000 |
| SteamAndHeat | 0.0000 | 0.000 | 0.0000 | 0.2266 |
sim1.calculateCarbonFlows(countrygridmixes=countrygridmix_100RE20502100)
>>>> Calculating Carbon Flows <<<< Working on Scenario: PV_ICE ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: r_PERC ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: r_SHJ ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: r_TOPCon ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: r_IRENA ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: ex_Life ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: ex_High_eff ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: ex_Circular ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: h_EffLife ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: h_50PERC ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: h_RecycledPERC ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: h_Perovskite_life ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet Working on Scenario: h_Perovskite_Eff ******************** Working on Carbon for Module ==> Working on Carbon for Material : glass ==> Working on Carbon for Material : silicon ==> Working on Carbon for Material : silver ==> Working on Carbon for Material : aluminium_frames ==> Working on Carbon for Material : copper ==> Working on Carbon for Material : encapsulant ==> Working on Carbon for Material : backsheet
this will become the aggregate carbon results function
scenarios = sim1.scenario
#simply group mod and mats carbon dfs by scenario
sim_carbon_dfs = pd.DataFrame()
for scen in scenarios:
print(scen)
mod_carbon_scen_results = sim1.scenario[scen].dataOut_c.add_prefix(str(scen+'_'))
scenmatdc = pd.DataFrame()
for mat in MATERIALS:
print(mat)
mat_carbon_scen_results = sim1.scenario[scen].material[mat].matdataOut_c.add_prefix(str(scen+'_'+mat+'_'))
scenmatdc = pd.concat([scenmatdc,mat_carbon_scen_results], axis=1) #group all material dc
scen_carbon_results = pd.concat([mod_carbon_scen_results,scenmatdc], axis=1) #append mats to mod
sim_carbon_dfs = pd.concat([sim_carbon_dfs, scen_carbon_results], axis=1) #append all scens "raw" data
#FIX INDEX of dfs
sim_carbon_dfs.index = pd.RangeIndex(start=2000,stop=2101,step=1)
#return sim_carbon_results, sim_annual_carbon
PV_ICE glass silicon silver aluminium_frames copper encapsulant backsheet r_PERC glass silicon silver aluminium_frames copper encapsulant backsheet r_SHJ glass silicon silver aluminium_frames copper encapsulant backsheet r_TOPCon glass silicon silver aluminium_frames copper encapsulant backsheet r_IRENA glass silicon silver aluminium_frames copper encapsulant backsheet ex_Life glass silicon silver aluminium_frames copper encapsulant backsheet ex_High_eff glass silicon silver aluminium_frames copper encapsulant backsheet ex_Circular glass silicon silver aluminium_frames copper encapsulant backsheet h_EffLife glass silicon silver aluminium_frames copper encapsulant backsheet h_50PERC glass silicon silver aluminium_frames copper encapsulant backsheet h_RecycledPERC glass silicon silver aluminium_frames copper encapsulant backsheet h_Perovskite_life glass silicon silver aluminium_frames copper encapsulant backsheet h_Perovskite_Eff glass silicon silver aluminium_frames copper encapsulant backsheet
#Do math on the carbon dfs, take in the output aggregate sim df
sim_annual_carbon = pd.DataFrame()
for scen in scenarios:
mod_mfg_carbon_total = sim_carbon_dfs.filter(like=scen).filter(like='Global_mod_MFG') #annual mfging elec carbon
mod_nonvMFG = ['Install','OandM','Repair','Demount','Store','Resell','ReMFG','Recycle'] #could remove from loop
nonvMFG_search = '|'.join(mod_nonvMFG) #create nonRE search
mod_carbon_sum_nonvmfg = sim_carbon_dfs.loc[:,sim_carbon_dfs.columns.str.contains(nonvMFG_search)].filter(like=scen).filter(like='_mod_') #annual non mfging carbon
scen_annual_carbon_mod = pd.concat([mod_mfg_carbon_total,mod_carbon_sum_nonvmfg], axis=1)
scen_annual_carbon_mod[scen+'_Annual_Emit_mod_elec_gCO2eq'] = scen_annual_carbon_mod.sum(axis=1)
scenmatdcmaths = pd.DataFrame()
for mat in MATERIALS:
scen_mat_dc_temp = sim_carbon_dfs.filter(like=scen).filter(like=mat)
#calculation for annual carbon emissions total (selecting to avoid double countings)
mat_global_vmfg_elec = scen_mat_dc_temp.filter(like='Global_vmfg_elec') #select global mod mfging
mat_vmfg_countries = scen_mat_dc_temp.filter(like='vmfg_elec') #select country specific mod mfging, includes global
mat_emit_lifecycle = scen_mat_dc_temp.loc[:,~scen_mat_dc_temp.columns.isin(mat_vmfg_countries.columns)] #select everything not the two above
scen_mat_annual_carbon = pd.concat([mat_global_vmfg_elec,mat_emit_lifecycle], axis=1) #group global mod, lifecycle
scen_mat_annual_carbon[scen+'_Annual_Emit_'+mat+'_gCO2eq'] = scen_mat_annual_carbon.sum(axis=1) #sum annual emit
scenmatdcmaths = pd.concat([scenmatdcmaths,scen_mat_annual_carbon], axis=1)
#add by material
#add by process, fuel, elec
#mat_ce_recycle = mat_carbon_scen_results.filter(like='Recycle_e_p')
#mat_ce_remfg = mat_carbon_scen_results.filter(like='ReMFG_clean')
#mat_landfill = mat_carbon_scen_results.filter(like='landfill_total')
#mat_scen_annual_carbon = pd.concat([mat_vmfg_total,mat_ce_recycle,mat_ce_remfg,mat_landfill], axis=1)
scen_modmat_annual_carbon = pd.concat([scen_annual_carbon_mod,scenmatdcmaths], axis=1)
scen_modmat_annual_carbon[scen+'_Annual_Emit_total_modmats_gCO2eq'] = scen_modmat_annual_carbon.filter(like='Annual_Emit').sum(axis=1)
sim_annual_carbon = pd.concat([sim_annual_carbon, scen_modmat_annual_carbon], axis=1)
#FIX INDEX of dfs
sim_annual_carbon.index = pd.RangeIndex(start=2000,stop=2101,step=1)
#create cumulative
sim_cumu_carbon = sim_annual_carbon.cumsum()
maxy = round(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats_gCO2eq').max()/1e12,-3) #for graphing
sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats_gCO2eq')
PV_ICE_Annual_Emit_total_modmats_gCO2eq 2.964207e+16 r_PERC_Annual_Emit_total_modmats_gCO2eq 2.210524e+16 r_SHJ_Annual_Emit_total_modmats_gCO2eq 2.104457e+16 r_TOPCon_Annual_Emit_total_modmats_gCO2eq 2.148850e+16 r_IRENA_Annual_Emit_total_modmats_gCO2eq 3.221499e+16 ex_Life_Annual_Emit_total_modmats_gCO2eq 2.274670e+16 ex_High_eff_Annual_Emit_total_modmats_gCO2eq 3.053505e+16 ex_Circular_Annual_Emit_total_modmats_gCO2eq 2.804816e+16 h_EffLife_Annual_Emit_total_modmats_gCO2eq 2.295700e+16 h_50PERC_Annual_Emit_total_modmats_gCO2eq 2.283846e+16 h_RecycledPERC_Annual_Emit_total_modmats_gCO2eq 2.347228e+16 h_Perovskite_life_Annual_Emit_total_modmats_gCO2eq 2.697990e+16 h_Perovskite_Eff_Annual_Emit_total_modmats_gCO2eq 2.349308e+16 Name: 2100, dtype: float64
sim_cumu_carbon_mmt = sim_cumu_carbon.filter(like='Annual_Emit_total_modmats_gCO2eq')/1e12
sim_cumu_carbon_mmt
| PV_ICE_Annual_Emit_total_modmats_gCO2eq | r_PERC_Annual_Emit_total_modmats_gCO2eq | r_SHJ_Annual_Emit_total_modmats_gCO2eq | r_TOPCon_Annual_Emit_total_modmats_gCO2eq | r_IRENA_Annual_Emit_total_modmats_gCO2eq | ex_Life_Annual_Emit_total_modmats_gCO2eq | ex_High_eff_Annual_Emit_total_modmats_gCO2eq | ex_Circular_Annual_Emit_total_modmats_gCO2eq | h_EffLife_Annual_Emit_total_modmats_gCO2eq | h_50PERC_Annual_Emit_total_modmats_gCO2eq | h_RecycledPERC_Annual_Emit_total_modmats_gCO2eq | h_Perovskite_life_Annual_Emit_total_modmats_gCO2eq | h_Perovskite_Eff_Annual_Emit_total_modmats_gCO2eq | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2000 | 1.436637 | 1.248665 | 1.199394 | 1.223802 | 1.436637 | 1.339473 | 1.194566 | 1.436637 | 1.194566 | 1.339473 | 1.462665 | 1.436637 | 1.436637 |
| 2001 | 1.909237 | 1.775803 | 1.740827 | 1.758153 | 1.909237 | 1.840264 | 1.737400 | 1.909237 | 1.737400 | 1.840264 | 1.944515 | 1.909237 | 1.909237 |
| 2002 | 2.413579 | 2.247151 | 2.203526 | 2.225136 | 2.413579 | 2.327551 | 2.199252 | 2.413579 | 2.199252 | 2.327551 | 2.460202 | 2.413579 | 2.413579 |
| 2003 | 3.097123 | 2.885977 | 2.830631 | 2.858048 | 3.097121 | 2.987980 | 2.825208 | 3.097123 | 2.825208 | 2.987980 | 3.161400 | 3.097123 | 3.097123 |
| 2004 | 4.328861 | 4.037132 | 3.960664 | 3.998544 | 4.328843 | 4.178064 | 3.953171 | 4.328861 | 3.953171 | 4.178064 | 4.428316 | 4.328861 | 4.328861 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2096 | 28440.242934 | 21552.285719 | 20518.555813 | 20951.276320 | 30544.274814 | 20750.854245 | 28271.738204 | 27154.070900 | 22397.551464 | 21400.300884 | 22542.646919 | 26307.102565 | 22731.510374 |
| 2097 | 28713.313526 | 21735.274796 | 20692.626559 | 21129.057883 | 30961.711458 | 21224.619726 | 28813.300118 | 27378.725357 | 22531.730102 | 21753.030840 | 22765.126159 | 26466.257999 | 22921.105303 |
| 2098 | 29003.781584 | 21857.338175 | 20808.742681 | 21247.649219 | 31380.505264 | 21716.414143 | 29373.501078 | 27602.699149 | 22668.934486 | 22111.322011 | 22992.241094 | 26626.408303 | 23111.228856 |
| 2099 | 29311.889152 | 21980.530888 | 20925.933074 | 21367.337730 | 31797.587613 | 22224.607777 | 29947.906169 | 27825.867869 | 22810.230956 | 22473.740092 | 23228.291931 | 26787.725830 | 23301.886569 |
| 2100 | 29642.071628 | 22105.244013 | 21044.569746 | 21488.503353 | 32214.986299 | 22746.698479 | 30535.051871 | 28048.159358 | 22957.003214 | 22838.456854 | 23472.280720 | 26979.902562 | 23493.079852 |
101 rows × 13 columns
fig_cumu_carbon, (ax1,ax2,ax3) = plt.subplots(1,3,figsize=(15,5), sharey=True, sharex=True,
gridspec_kw={'wspace':0})
#BAU
ax1.set_prop_cycle(color=colorpalette[0:5])
ax1.plot(sim_cumu_carbon_mmt.iloc[:,0:5], label=scennames_labels_flat[0:5]) # baselines
ax1.set_title('Business as Usual', fontsize=14)
ax1.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes $CO_{2eq}$]', fontsize=20)
ax1.set_xlim(2000,2100)
ax1.legend(bbox_to_anchor=(0.9,-0.05))
ax1.set_ylim(0,maxy+1000)
ax1.xaxis.set_minor_locator(MultipleLocator(10))
ax1.grid(axis='both', which='both', color='0.9', ls='--')
#Extreme
ax2.set_prop_cycle(color=colorpalette[5:8])
ax2.plot(sim_cumu_carbon_mmt.iloc[:,5:8], label=scennames_labels_flat[5:8])
ax2.xaxis.set_minor_locator(MultipleLocator(10))
ax2.grid(axis='both', which='both', color='0.9', ls='--')
#create glowlines for Extreme scens
n_lines = 10
diff_linewidth = 1.05
alpha_value = 0.05
for n in range(1, n_lines+1):
ax2.plot(sim_cumu_carbon_mmt.iloc[:,5],
linewidth=2+(diff_linewidth*n),
alpha=alpha_value,
color=colorpalette[5])
for n in range(1, n_lines+1):
ax2.plot(sim_cumu_carbon_mmt.iloc[:,6],
linewidth=2+(diff_linewidth*n),
alpha=alpha_value,
color=colorpalette[6])
for n in range(1, n_lines+1):
ax2.plot(sim_cumu_carbon_mmt.iloc[:,7],
linewidth=2+(diff_linewidth*n),
alpha=alpha_value,
color=colorpalette[7])
ax2.set_title('Extreme', fontsize=14)
ax2.legend(bbox_to_anchor=(0.9,-0.05))
#Ambitious
ax3.set_prop_cycle(color=colorpalette[8:])
ax3.plot(sim_cumu_carbon_mmt.iloc[:,8:], label=scennames_labels_flat[8:], ls='--')#
ax3.set_title('Ambitious', fontsize=14)
ax3.legend(bbox_to_anchor=(1.05,-0.05)) #(x,y)
ax3.xaxis.set_minor_locator(MultipleLocator(10))
ax3.grid(axis='both', which='both', color='0.9', ls='--')
#overall figure
fig_cumu_carbon.suptitle('Cumulative Carbon Emissions', fontsize=24, y=1)
plt.show()
#fig_cumu_carbon.savefig('energyresults-annualMatDemands-decade.png', dpi=300, bbox_inches='tight')
#comparing to Ember open source data, uses a lifecycle PV emission factor from IPCC for electricity carbon
ember_PVCO2 = pd.read_csv(os.path.join(carbonfolder,'Ember-PVEmissionsWorld2000-2022.csv'), index_col='year')
#ember_PVCO2['emissions_mtco2'] #ANNUAL DATA
ember_PVCO2_cumu = ember_PVCO2.cumsum()
#compare to Fthenakis and Leccisi 2021 analysis
FL2021_gwp_scSi2020 = 1010 #kg CO2eq/kWp from Fthenakis and Leccisi 2021 "sc_Si 2020"
FL2021_gwp_scSi2015 = 2000 #"scSi 2015"
FL2021_gwp_mcSi2020 = 1087 #mcSi 2020
FL2021_gwp_mcSi2015 = 1435 #mcSi 2015
kw_installed_pvice = sim1.scenario['PV_ICE'].dataIn_m['new_Installed_Capacity_[MW]']*1000 # kW installed
FL2021_gwp_range = pd.DataFrame(index=ember_PVCO2.index)
FL2021_gwp_range['F&L_sc-Si_2020'] = kw_installed_pvice.loc[:22].values*FL2021_gwp_scSi2020
FL2021_gwp_range['F&L_sc-Si_2015'] = kw_installed_pvice.loc[:22].values*FL2021_gwp_scSi2015
FL2021_gwp_range['F&L_mc-Si_2020'] = kw_installed_pvice.loc[:22].values*FL2021_gwp_mcSi2020
FL2021_gwp_range['F&L_mc-Si_2015'] = kw_installed_pvice.loc[:22].values*FL2021_gwp_mcSi2015
FL2021_gwp_range_cumu_mmt = FL2021_gwp_range.cumsum()/1e9 #cumulative, and kg to million metric tonnes
#compare to Ultra Low Carbon Solar Alliance South Korea rating, as redproduced in Polverini 2023
Polverini2023_low = 550 #kg CO2eq/kWp "France"
Polverini2023_high = 762 #kg CO2eq/kWp "China"
kw_installed_pvice = sim1.scenario['PV_ICE'].dataIn_m['new_Installed_Capacity_[MW]']*1000 # kW installed
Polverini2023_gwp_range = pd.DataFrame(index=ember_PVCO2.index)
Polverini2023_gwp_range['Polverini2023_low'] = kw_installed_pvice.loc[:22].values*Polverini2023_low
Polverini2023_gwp_range['Polverini2023_high'] = kw_installed_pvice.loc[:22].values*Polverini2023_high
Polverini2023_gwp_range_cumu_mmt = Polverini2023_gwp_range.cumsum()/1e9 #cumulative, and kg to million metric tonnes
#compare to Liang and You 2023, using Figure 1 2020 values from a and e
LiangYou2023_scSi_low = 250 #kg CO2eq/m2 ""
LiangYou2023_scSi_high = 350 #kg CO2eq/m2 ""
LiangYou2023_mcSi_low = 210
LiangYou2023_mcSi_high = 300
m2_installed_pvice = sim1.scenario['PV_ICE'].dataOut_m['Area'] # area deployed in m2
LiangYou2023_gwp_range = pd.DataFrame(index=ember_PVCO2.index)
LiangYou2023_gwp_range['LiangYou2023_scSi_low'] = m2_installed_pvice.loc[:22].values*LiangYou2023_scSi_low
LiangYou2023_gwp_range['LiangYou2023_scSi_high'] = m2_installed_pvice.loc[:22].values*LiangYou2023_scSi_high
LiangYou2023_gwp_range['LiangYou2023_mcSi_low'] = m2_installed_pvice.loc[:22].values*LiangYou2023_mcSi_low
LiangYou2023_gwp_range['LiangYou2023_mcSi_high'] = m2_installed_pvice.loc[:22].values*LiangYou2023_mcSi_high
LiangYou2023_gwp_range_cumu_mmt = LiangYou2023_gwp_range.cumsum()/1e9 #cumulative, and kg to million metric tonnes
plt.plot(sim_cumu_carbon_mmt.loc[:2022,'PV_ICE_Annual_Emit_total_modmats_gCO2eq'], label='PV_ICE', color='black')
plt.plot(LiangYou2023_gwp_range_cumu_mmt['LiangYou2023_scSi_low'], label='LiangYou2023_scSi_low', color='violet', ls='-.')
plt.plot(LiangYou2023_gwp_range_cumu_mmt['LiangYou2023_scSi_high'], label='LiangYou2023_scSi_high', color='mediumorchid', ls='-.')
plt.plot(LiangYou2023_gwp_range_cumu_mmt['LiangYou2023_mcSi_low'], label='LiangYou2023_mcSi_low', color='darkviolet', ls=':')
plt.plot(LiangYou2023_gwp_range_cumu_mmt['LiangYou2023_mcSi_high'], label='LiangYou2023_mcSi_high', color='blueviolet', ls=':')
plt.plot(FL2021_gwp_range_cumu_mmt['F&L_sc-Si_2020'], label='FthenakisLeccisi2021_sc-Si_2020', color='lightcoral', ls='-.')
plt.plot(FL2021_gwp_range_cumu_mmt.loc[:2015,'F&L_sc-Si_2015'], label='FthenakisLeccisi2021_sc-Si_2015', color='indianred', ls='-.')
plt.plot(FL2021_gwp_range_cumu_mmt['F&L_mc-Si_2020'], label='FthenakisLeccisi2021_mc-Si_2020', color='firebrick', ls='dotted')
plt.plot(FL2021_gwp_range_cumu_mmt.loc[:2015,'F&L_mc-Si_2015'], label='FthenakisLeccisi2021_mc-Si_2015', color='maroon', ls='dotted')
plt.plot(Polverini2023_gwp_range_cumu_mmt['Polverini2023_low'], label='Polverini2023_low', color='deepskyblue', ls='--')
plt.plot(Polverini2023_gwp_range_cumu_mmt['Polverini2023_high'], label='Polverini2023_high', color='dodgerblue', ls='--')
plt.plot(ember_PVCO2_cumu.index, ember_PVCO2_cumu['emissions_mtco2'], label='Ember_electricity', color='green', ls='--')
plt.ylabel('Cumulative Carbon\n[$CO_{2eq}$ million metric tonnes]')
plt.title('Cumulative Carbon Emissions from PV')
plt.xlim(2000,2025)
plt.ylim(0,)
plt.legend(loc='upper left', fontsize=12)
<matplotlib.legend.Legend at 0x1fb298b8520>
This is a simple way of doing it, will not work for much beyond 2022, because the annual emissions include end of life of other systems, not just the mfging of installed - its not necessarily fair. Might work out on balance, kinda
#lit factors into scatter points
litfactors = pd.DataFrame(index=ember_PVCO2_cumu.index)
litfactors.loc[2022,'Polverini2023_low'] = Polverini2023_low
litfactors.loc[2022,'Polverini2023_high'] = Polverini2023_high
litfactors.loc[2020,'FthenakisLeccisi2021_scSi'] = FL2021_gwp_scSi2020
litfactors.loc[2015,'FthenakisLeccisi2021_scSi'] = FL2021_gwp_scSi2015
litfactors.loc[2020,'FthenakisLeccisi2021_mcSi'] = FL2021_gwp_mcSi2020
litfactors.loc[2015,'FthenakisLeccisi2021_mcSi'] = FL2021_gwp_mcSi2015
litfactors.loc[2020,'LiangYou2023_scSi_m$^{2}$'] = LiangYou2023_scSi_low #kg CO2eq/m2 ""
litfactors.loc[2019,'LiangYou2023_scSi_m$^{2}$'] = LiangYou2023_scSi_high #kg CO2eq/m2 ""
litfactors.loc[2020,'LiangYou2023_mcSi_m$^{2}$'] = LiangYou2023_mcSi_low
litfactors.loc[2019,'LiangYou2023_mcSi_m$^{2}$'] = LiangYou2023_mcSi_high
litfactors.loc[2015,'Anctil2021_low'] = 1010
litfactors.loc[2015,'Anctil2021_high'] = 1775
litfactors.loc[2020,'Anctil2021_low'] = 500
litfactors.loc[2020,'Anctil2021_high'] = 750
litfactors.loc[2005,'AlsemadeWild2005_scSi'] = 41 #g/kWh/1000 = kg/kWh *1275 kw
#litfactors
#calculate CO2eq/kWp by dividing annual CO2eq/deployed PV
installs = pd.DataFrame(kw_installed_pvice.loc[:22])
installs.index = ember_PVCO2_cumu.index
pvice_emit_annual = sim_annual_carbon.filter(like='PV_ICE').filter(like='Annual_Emit_total_modmats_gCO2eq').loc[:2022]
pvice_annual_kgco2pkwp = pvice_emit_annual['PV_ICE_Annual_Emit_total_modmats_gCO2eq'].div(installs['new_Installed_Capacity_[MW]'], axis=0)/1e3
#pvice_annual_kgco2pkwp
#calculate CO2eq/m2 for PV ICE
meters2installs = pd.DataFrame(m2_installed_pvice.loc[:22])
meters2installs.index = ember_PVCO2_cumu.index
pvice_annual_kgco2eqpm2 = pvice_emit_annual['PV_ICE_Annual_Emit_total_modmats_gCO2eq'].div(meters2installs['Area'], axis=0)/1e3
#pvice_annual_kgco2eqpm2
litfactors.columns
Index(['Polverini2023_low', 'Polverini2023_high', 'FthenakisLeccisi2021_scSi',
'FthenakisLeccisi2021_mcSi', 'LiangYou2023_scSi_m$^{2}$',
'LiangYou2023_mcSi_m$^{2}$'],
dtype='object')
#graphing
plt.plot(pvice_annual_kgco2eqpm2, label='PV_ICE kg CO$_{2}$eq/m$^{2}$', color='darkgray')
plt.plot(pvice_annual_kgco2pkwp, label='PV_ICE kg CO$_{2}$eq/kW$_{p}$', color='black')
plt.scatter(litfactors.index, litfactors['Polverini2023_low'], label='Polverini2023_low', color='deepskyblue')
plt.scatter(litfactors.index, litfactors['Polverini2023_high'], label='Polverini2023_high', color='dodgerblue')
plt.scatter(litfactors.index, litfactors['FthenakisLeccisi2021_scSi'], label='FthenakisLeccisi2021_scSi', color='lightcoral')
plt.scatter(litfactors.index, litfactors['FthenakisLeccisi2021_mcSi'], label='FthenakisLeccisi2021_mcSi', color='firebrick')
plt.scatter(litfactors.index, litfactors['LiangYou2023_scSi_m$^{2}$'], label='LiangYou2023_scSi_m$^{2}$', color='violet')
plt.scatter(litfactors.index, litfactors['LiangYou2023_mcSi_m$^{2}$'], label='LiangYou2023_mcSi_m$^{2}$', color='darkviolet')
plt.scatter(litfactors.index, litfactors['Anctil2021_low'], label='Anctil2021_low', color='green')
plt.scatter(litfactors.index, litfactors['Anctil2021_high'], label='Anctil2021_high', color='limegreen')
plt.ylabel('kg CO$_{2}$eq/kW$_{p}$ OR kg CO$_{2}$eq/m$^{2}$')
plt.title('Literature Comparison:\nkg CO$_{2}$eq/kW$_{p}$')
plt.legend(bbox_to_anchor=(1.6,1))
<matplotlib.legend.Legend at 0x1fb348effd0>
for scen in scenarios:
scen_annual_carbon = sim_annual_carbon.filter(like='Annual_Emit').filter(like=scen)/1e12 #million tonnes
plt.plot([],[],color=colormats[0], label=MATERIALS[0])
plt.plot([],[],color=colormats[1], label=MATERIALS[1])
plt.plot([],[],color=colormats[2], label=MATERIALS[2])
plt.plot([],[],color=colormats[3], label=MATERIALS[3])
plt.plot([],[],color=colormats[4], label=MATERIALS[4])
plt.plot([],[],color=colormats[5], label=MATERIALS[5])
plt.plot([],[],color=colormats[6], label=MATERIALS[6])
plt.plot([],[],color=colormats[7], label='module')
plt.stackplot(scen_annual_carbon.index,
scen_annual_carbon[scen+'_Annual_Emit_glass_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_silicon_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_silver_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_aluminium_frames_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_copper_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_encapsulant_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_backsheet_gCO2eq'],
scen_annual_carbon[scen+'_Annual_Emit_mod_elec_gCO2eq'],
colors = colormats)
plt.title(scen+':\nGHG Emissions Annually by Module and Material Lifecycle')
plt.ylabel('GHG Emissions Annually from Lifecycle Mats and Mods\n[million metric tonnes $CO_{2eq}$]')
plt.xlim(2000,2100)
handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.45,1))
#plt.legend()
plt.show()
maxy
32000.0
#colormats = ['#00bfbf','#ff7f0e','#1f77be','#2ca02c','#d62728','#9467BD','#8C564B','black'] #colors for material plots
for scen in scenarios:
scen_cumu_carbon = sim_cumu_carbon.filter(like='Annual_Emit').filter(like=scen)/1e12 #million tonnes
plt.plot([],[],color=colormats[0], label=MATERIALS[0])
plt.plot([],[],color=colormats[1], label=MATERIALS[1])
plt.plot([],[],color=colormats[2], label=MATERIALS[2])
plt.plot([],[],color=colormats[3], label=MATERIALS[3])
plt.plot([],[],color=colormats[4], label=MATERIALS[4])
plt.plot([],[],color=colormats[5], label=MATERIALS[5])
plt.plot([],[],color=colormats[6], label=MATERIALS[6])
plt.plot([],[],color=colormats[7], label='module')
plt.stackplot(scen_cumu_carbon.index,
scen_cumu_carbon[scen+'_Annual_Emit_glass_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_silicon_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_silver_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_aluminium_frames_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_copper_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_encapsulant_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_backsheet_gCO2eq'],
scen_cumu_carbon[scen+'_Annual_Emit_mod_elec_gCO2eq'],
colors = colormats)
plt.title(scen+':\nGHG Emissions Annually by Module and Material Lifecycle')
plt.ylabel('GHG Emissions Annually from Lifecycle Mats and Mods\n[million metric tonnes $CO_{2eq}$]')
plt.xlim(2000,2100)
plt.ylim(0,maxy+1000)
handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.45,1))
plt.grid(axis='both', which='both', color='0.9', ls='--')
#plt.legend()
plt.show()
sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_mod_elec')
PV_ICE_Annual_Emit_mod_elec_gCO2eq 8.661511e+13 r_PERC_Annual_Emit_mod_elec_gCO2eq 7.955485e+13 r_SHJ_Annual_Emit_mod_elec_gCO2eq 7.575890e+13 r_TOPCon_Annual_Emit_mod_elec_gCO2eq 7.733545e+13 r_IRENA_Annual_Emit_mod_elec_gCO2eq 1.014963e+14 ex_Life_Annual_Emit_mod_elec_gCO2eq 8.112453e+13 ex_High_eff_Annual_Emit_mod_elec_gCO2eq 6.481039e+13 ex_Circular_Annual_Emit_mod_elec_gCO2eq 1.238429e+14 h_EffLife_Annual_Emit_mod_elec_gCO2eq 6.864642e+13 h_50PERC_Annual_Emit_mod_elec_gCO2eq 8.163300e+13 h_RecycledPERC_Annual_Emit_mod_elec_gCO2eq 3.024845e+14 h_Perovskite_life_Annual_Emit_mod_elec_gCO2eq 1.173374e+14 h_Perovskite_Eff_Annual_Emit_mod_elec_gCO2eq 1.055897e+14 Name: 2100, dtype: float64
#create a df from which to do a bar chart of 2100 emissions by mat/mod
mats_emit_2100 = pd.DataFrame() #index=scennames_labels_flat
for mat in MATERIALS:
mat_emit_2100 = pd.Series(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_'+mat).values)
mats_emit_2100 = pd.concat([mats_emit_2100, mat_emit_2100], axis=1)
mats_emit_2100
mats_emit_2100.columns = MATERIALS
modmats_emit_2100 = pd.concat([mats_emit_2100,pd.Series(sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_mod_elec').values)], axis=1)
modmats_emit_2100.index = scennames_labels_flat
modmats_emit_2100.rename(columns={0:'module'}, inplace=True)
modmats_emit_2100_megatonne = modmats_emit_2100/1e12
modmats_emit_2100_megatonne
| glass | silicon | silver | aluminium_frames | copper | encapsulant | backsheet | module | |
|---|---|---|---|---|---|---|---|---|
| PV_ICE | 10128.661994 | 6393.528822 | 39.555545 | 7759.907146 | 8.553999 | 3013.443849 | 2211.805161 | 86.615111 |
| PERC | 9100.755660 | 5083.297261 | 25.191311 | 4986.668409 | 7.933845 | 2800.113453 | 21.729228 | 79.554845 |
| SHJ | 8652.812210 | 4837.013804 | 44.794737 | 4742.685932 | 7.545504 | 2662.628153 | 21.330504 | 75.758903 |
| TOPCon | 8837.278528 | 4938.802814 | 43.333633 | 4843.242140 | 7.705695 | 2719.277076 | 21.528020 | 77.335447 |
| Low Quality | 11526.374030 | 5202.740656 | 40.635431 | 7133.665114 | 12.970040 | 4731.060652 | 3466.044108 | 101.496270 |
| Long-Lived | 9270.300576 | 5078.154692 | 29.471217 | 6013.562121 | 6.784228 | 2244.838020 | 22.463092 | 81.124534 |
| High Eff | 12963.265329 | 6145.955317 | 38.732726 | 8176.784091 | 8.755677 | 3115.456836 | 21.291503 | 64.810392 |
| Circular | 8996.350286 | 4412.185490 | 92.251404 | 6254.983351 | 21.597082 | 8123.698405 | 23.250434 | 123.842906 |
| High Eff + Long-life | 9507.952013 | 4926.966042 | 31.290604 | 6098.983567 | 6.741955 | 2295.131175 | 21.291435 | 68.646424 |
| Long-Life + Recycling | 9444.863234 | 5171.277979 | 32.719877 | 5717.789805 | 6.882528 | 2360.827092 | 22.463337 | 81.633002 |
| Recycled-Si + Long-life | 8876.675002 | 2259.159910 | 33.593199 | 4978.766570 | 11.277104 | 4044.829561 | 2965.494878 | 302.484496 |
| Circular + Long-life | 8839.142638 | 6474.457856 | 66.818549 | 5916.944139 | 15.130176 | 5526.821345 | 23.250434 | 117.337425 |
| Circular + High Eff | 6880.106946 | 5865.683841 | 68.893415 | 4657.933648 | 15.835931 | 5875.785931 | 23.250434 | 105.589706 |
fig_cumuemit_modmat, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True,
gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['glass'], color=colormats[0])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['silicon'],
bottom=modmats_emit_2100_megatonne[0:5]['glass'], color=colormats[1])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['silver'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:2].sum(axis=1), color=colormats[2])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['aluminium_frames'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:3].sum(axis=1), color=colormats[3])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['copper'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:4].sum(axis=1), color=colormats[4])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['encapsulant'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:5].sum(axis=1), color=colormats[5])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['backsheet'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:6].sum(axis=1), color=colormats[6])
ax0.bar(scennames_labels[0:5], modmats_emit_2100_megatonne[0:5]['module'],
bottom=modmats_emit_2100_megatonne.iloc[0:5,0:7].sum(axis=1), color='black')
ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes $CO_{2eq}$]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--')
ax0.set_axisbelow(True)
#Extreme
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['glass'], color=colormats[0])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['silicon'],
bottom=modmats_emit_2100_megatonne[5:8]['glass'], color=colormats[1])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['silver'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:2].sum(axis=1), color=colormats[2])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['aluminium_frames'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:3].sum(axis=1), color=colormats[3])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['copper'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:4].sum(axis=1), color=colormats[4])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['encapsulant'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:5].sum(axis=1), color=colormats[5])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['backsheet'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:6].sum(axis=1), color=colormats[6])
ax2.bar(scennames_labels[5:8], modmats_emit_2100_megatonne[5:8]['module'],
bottom=modmats_emit_2100_megatonne.iloc[5:8,0:7].sum(axis=1), color='black')
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--')
ax2.set_axisbelow(True)
#Ambitious
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['glass'], color=colormats[0])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['silicon'],
bottom=modmats_emit_2100_megatonne[8:]['glass'], color=colormats[1])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['silver'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:2].sum(axis=1), color=colormats[2])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['aluminium_frames'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:3].sum(axis=1), color=colormats[3])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['copper'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:4].sum(axis=1), color=colormats[4])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['encapsulant'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:5].sum(axis=1), color=colormats[5])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['backsheet'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:6].sum(axis=1), color=colormats[6])
ax3.bar(scennames_labels[8:], modmats_emit_2100_megatonne[8:]['module'],
bottom=modmats_emit_2100_megatonne.iloc[8:,0:7].sum(axis=1), color='black')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--')
ax3.set_axisbelow(True)
#overall fig
fig_cumuemit_modmat.suptitle('Cumulative Emisisons in 2100 by material', fontsize=24)
plt.show()
#fig_cumuemit_modmat.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\3630820325.py:23: UserWarning: FixedFormatter should only be used together with FixedLocator ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45) C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\3630820325.py:45: UserWarning: FixedFormatter should only be used together with FixedLocator ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45) C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\3630820325.py:68: UserWarning: FixedFormatter should only be used together with FixedLocator ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
cumu_emit_sum = modmats_emit_2100_megatonne.sum(axis=1)
fraction_modmats_cumu_emit = modmats_emit_2100_megatonne.div(cumu_emit_sum, axis=0)*100
fraction_modmats_cumu_emit
| glass | silicon | silver | aluminium_frames | copper | encapsulant | backsheet | module | |
|---|---|---|---|---|---|---|---|---|
| PV_ICE | 34.169886 | 21.569103 | 0.133444 | 26.178694 | 0.028858 | 10.166104 | 7.461709 | 0.292203 |
| PERC | 41.170121 | 22.995888 | 0.113961 | 22.558758 | 0.035891 | 12.667191 | 0.098299 | 0.359891 |
| SHJ | 41.116603 | 22.984617 | 0.212857 | 22.536388 | 0.035855 | 12.652329 | 0.101359 | 0.359993 |
| TOPCon | 41.125612 | 22.983466 | 0.201660 | 22.538760 | 0.035860 | 12.654567 | 0.100184 | 0.359892 |
| Low Quality | 35.779540 | 16.150063 | 0.126138 | 22.143933 | 0.040261 | 14.685900 | 10.759105 | 0.315059 |
| Long-Lived | 40.754488 | 22.324799 | 0.129563 | 26.437077 | 0.029825 | 9.868852 | 0.098753 | 0.356643 |
| High Eff | 42.453720 | 20.127542 | 0.126847 | 26.778353 | 0.028674 | 10.202887 | 0.069728 | 0.212249 |
| Circular | 32.074655 | 15.730749 | 0.328904 | 22.300869 | 0.077000 | 28.963392 | 0.082895 | 0.441537 |
| High Eff + Long-life | 41.416347 | 21.461713 | 0.136301 | 26.566985 | 0.029368 | 9.997521 | 0.092745 | 0.299022 |
| Long-Life + Recycling | 41.355085 | 22.642852 | 0.143267 | 25.035797 | 0.030136 | 10.337069 | 0.098358 | 0.357437 |
| Recycled-Si + Long-life | 37.817693 | 9.624799 | 0.143119 | 21.211260 | 0.048044 | 17.232367 | 12.634030 | 1.288688 |
| Circular + Long-life | 32.761952 | 23.997336 | 0.247660 | 21.930932 | 0.056079 | 20.484957 | 0.086177 | 0.434907 |
| Circular + High Eff | 29.285675 | 24.967709 | 0.293250 | 19.826833 | 0.067407 | 25.010709 | 0.098967 | 0.449450 |
fig_cumuemit_modmat, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True,
gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['glass'], color=colormats[0])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['silicon'],
bottom=fraction_modmats_cumu_emit[0:5]['glass'], color=colormats[1])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['silver'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:2].sum(axis=1), color=colormats[2])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['aluminium_frames'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:3].sum(axis=1), color=colormats[3])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['copper'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:4].sum(axis=1), color=colormats[4])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['encapsulant'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:5].sum(axis=1), color=colormats[5])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['backsheet'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:6].sum(axis=1), color=colormats[6])
ax0.bar(scennames_labels[0:5], fraction_modmats_cumu_emit[0:5]['module'],
bottom=fraction_modmats_cumu_emit.iloc[0:5,0:7].sum(axis=1), color='black')
ax0.set_ylim(0,100)
ax0.set_ylabel('Percent Emissions by Material\n[%]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--')
ax0.set_axisbelow(True)
#Extreme
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['glass'], color=colormats[0])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['silicon'],
bottom=fraction_modmats_cumu_emit[5:8]['glass'], color=colormats[1])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['silver'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:2].sum(axis=1), color=colormats[2])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['aluminium_frames'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:3].sum(axis=1), color=colormats[3])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['copper'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:4].sum(axis=1), color=colormats[4])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['encapsulant'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:5].sum(axis=1), color=colormats[5])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['backsheet'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:6].sum(axis=1), color=colormats[6])
ax2.bar(scennames_labels[5:8], fraction_modmats_cumu_emit[5:8]['module'],
bottom=fraction_modmats_cumu_emit.iloc[5:8,0:7].sum(axis=1), color='black')
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--')
ax2.set_axisbelow(True)
#Ambitious
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['glass'], color=colormats[0])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['silicon'],
bottom=fraction_modmats_cumu_emit[8:]['glass'], color=colormats[1])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['silver'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:2].sum(axis=1), color=colormats[2])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['aluminium_frames'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:3].sum(axis=1), color=colormats[3])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['copper'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:4].sum(axis=1), color=colormats[4])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['encapsulant'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:5].sum(axis=1), color=colormats[5])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['backsheet'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:6].sum(axis=1), color=colormats[6])
ax3.bar(scennames_labels[8:], fraction_modmats_cumu_emit[8:]['module'],
bottom=fraction_modmats_cumu_emit.iloc[8:,0:7].sum(axis=1), color='black')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--')
ax3.set_axisbelow(True)
#overall fig
fig_cumuemit_modmat.suptitle('Fraction of Emissions attribute to Module/Material', fontsize=24)
plt.show()
#fig_cumuemit_modmat.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\2389923115.py:23: UserWarning: FixedFormatter should only be used together with FixedLocator ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45) C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\2389923115.py:45: UserWarning: FixedFormatter should only be used together with FixedLocator ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45) C:\Users\hmirletz\AppData\Local\Temp\1\ipykernel_2108\2389923115.py:68: UserWarning: FixedFormatter should only be used together with FixedLocator ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
#mins in 2050 and 2100
cumu_carbon_2050 = sim_cumu_carbon.loc[2050].filter(like='Annual_Emit_total_modmats')/1e12
cumu_carbon_2100 = sim_cumu_carbon.loc[2100].filter(like='Annual_Emit_total_modmats')/1e12
cumu_carbon_rankings_crittime = pd.concat([cumu_carbon_2050,cumu_carbon_2100], axis=1)
cumu_carbon_rankings_crittime.index = scennames_labels_flat
cumu_carbon_rankings_crittime_bmt = cumu_carbon_rankings_crittime/1000
round(cumu_carbon_rankings_crittime_bmt,1)
| 2050 | 2100 | |
|---|---|---|
| PV_ICE | 14.1 | 29.6 |
| PERC | 12.8 | 22.1 |
| SHJ | 12.2 | 21.0 |
| TOPCon | 12.4 | 21.5 |
| Low Quality | 15.2 | 32.2 |
| Long-Lived | 13.4 | 22.7 |
| High Eff | 10.9 | 30.5 |
| Circular | 17.6 | 28.0 |
| High Eff + Long-life | 11.2 | 23.0 |
| Long-Life + Recycling | 13.4 | 22.8 |
| Recycled-Si + Long-life | 14.3 | 23.5 |
| Circular + Long-life | 18.3 | 27.0 |
| Circular + High Eff | 15.1 | 23.5 |
cumu_carbon_rankings_crittime_plot = cumu_carbon_rankings_crittime.copy()
cumu_carbon_rankings_crittime_plot['diff'] = cumu_carbon_rankings_crittime[2100]-cumu_carbon_rankings_crittime[2050]
fig_cumulativeemit, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True,
gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(cumu_carbon_rankings_crittime_plot.index[0:5], cumu_carbon_rankings_crittime_plot[2050].iloc[0:5],
tick_label=scennames_labels[0:5], color=colorpalette[0:5], alpha = 0.7, edgecolor='white')
ax0.bar(cumu_carbon_rankings_crittime_plot.index[0:5], cumu_carbon_rankings_crittime_plot['diff'].iloc[0:5],
bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[0:5],
tick_label=scennames_labels[0:5], color=colorpalette[0:5])
ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes $CO_{2eq}$]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--')
ax0.set_axisbelow(True)
#Extreme
ax2.bar(cumu_carbon_rankings_crittime_plot.index[5:8], cumu_carbon_rankings_crittime_plot[2050].iloc[5:8],
tick_label=scennames_labels[5:8], color=colorpalette[5:8], alpha = 0.7, edgecolor='white')
ax2.bar(cumu_carbon_rankings_crittime_plot.index[5:8], cumu_carbon_rankings_crittime_plot['diff'].iloc[5:8],
bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[5:8],
tick_label=scennames_labels[5:8], color=colorpalette[5:8])
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--')
ax2.set_axisbelow(True)
#Ambitious
ax3.bar(cumu_carbon_rankings_crittime_plot.index[8:], cumu_carbon_rankings_crittime_plot[2050].iloc[8:],
tick_label=scennames_labels[8:], color=colorpalette[8:], hatch='x', edgecolor='white', alpha=0.7)
ax3.bar(cumu_carbon_rankings_crittime_plot.index[8:], cumu_carbon_rankings_crittime_plot['diff'].iloc[8:],
bottom=cumu_carbon_rankings_crittime_plot[2050].iloc[8:],
tick_label=scennames_labels[8:], color=colorpalette[8:], hatch='x', edgecolor='white')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--')
ax3.set_axisbelow(True)
#overall fig
fig_cumulativeemit.suptitle('Cumulative Emissions in 2050, 2100', fontsize=24)
plt.show()
#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
process_emissions = pd.DataFrame()
for scen in scenarios:
scen_p = sim_carbon_dfs.filter(like=scen).filter(like='_p_')
scen_p_sum = scen_p.sum(axis=1)
process_emissions = pd.concat([process_emissions,scen_p_sum], axis=1)
process_emissions.columns = scennames_labels_flat
process_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
process_emissions_cumu = process_emissions.cumsum()
#process_emissions_cumu
This is capturing steam and heating fuel, also only on material level
fuel_emissions = pd.DataFrame()
for scen in scenarios:
scen_f = sim_carbon_dfs.filter(like=scen).filter(like='_fuel_')
scen_f_sum = scen_f.sum(axis=1)
fuel_emissions = pd.concat([fuel_emissions,scen_f_sum], axis=1)
fuel_emissions.columns = scennames_labels_flat
fuel_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
fuel_emissions_cumu = fuel_emissions.cumsum()
#fuel_emissions_cumu
both module and material level elec.
elec_emissions = pd.DataFrame()
for scen in scenarios:
scen_mod_elec = sim_carbon_dfs.filter(like=scen).filter(like='Global_mod_MFG') #module elec lifecycle emits
#material elec emits
mat_eleckey = ['Global_vmfg_elec','landfill_elec','ReMFG_clean_elec','Recycled_LQ_elec','Recycled_HQ_elec']
mat_elecs_search = '|'.join(mat_eleckey)
scen_mat_elecs = sim_carbon_dfs.loc[:,sim_carbon_dfs.columns.str.contains(mat_elecs_search)].filter(like=scen)
scen_mat_elecs_sum = scen_mat_elecs.sum(axis=1)
#sum them together by scen
scen_elec_modmat_annual_sum = scen_mat_elecs_sum+scen_mod_elec.iloc[:,0]
elec_emissions = pd.concat([elec_emissions,scen_elec_modmat_annual_sum], axis=1)
elec_emissions.columns=scennames_labels_flat
elec_emissions.index = pd.RangeIndex(start=2000,stop=2101,step=1)
elec_emissions_cumu = elec_emissions.cumsum()
#graphing by emission source
efp_emit_total = elec_emissions+fuel_emissions+process_emissions
efp_emit_total_cumu = elec_emissions_cumu+fuel_emissions_cumu+process_emissions_cumu
#graphing by emission source, annual
#efp_emit_total = elec_emissions+fuel_emissions+process_emissions
for scen in scennames_labels_flat:
plt.plot([],[],color='black', label='process')
plt.plot([],[],color='darkred', label='fuel')
plt.plot([],[],color='blue', label='electricity')
plt.stackplot(elec_emissions.index,
process_emissions[scen]/1e12,
fuel_emissions[scen]/1e12,
elec_emissions[scen]/1e12,
colors = ['black','darkred','blue'])
plt.title(scen+':\nGHG Emissions Annually by Source')
plt.ylabel('GHG Emissions Annually from Lifecycle Source\n[million metric tonnes $CO_{2eq}$]')
plt.xlim(2000,2100)
plt.ylim(0,)
handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.4,1))
#plt.grid(axis='both', which='both', color='0.9', ls='--', zorder=0)
#plt.set_axisbelow(True)
#plt.legend()
plt.show()
#graphing by emission source, cumulative
for scen in scennames_labels_flat:
plt.plot([],[],color='black', label='process')
plt.plot([],[],color='darkred', label='fuel')
plt.plot([],[],color='blue', label='electricity')
plt.stackplot(elec_emissions_cumu.index,
process_emissions_cumu[scen]/1e12,
fuel_emissions_cumu[scen]/1e12,
elec_emissions_cumu[scen]/1e12,
colors = ['black','darkred','blue'])
plt.title(scen+':\nGHG Emissions Cumulative by Source')
plt.ylabel('GHG Emissions Cumulatively from Lifecycle Source\n[million metric tonnes $CO_{2eq}$]')
plt.xlim(2000,2100)
plt.ylim(0,maxy+1000)
handles, labels = plt.gca().get_legend_handles_labels()
#specify order of items in legend
#order = [1,2,0]
#add legend to plot
#plt.legend([handles[idx] for idx in order],[labels[idx] for idx in order])
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.3,1))
plt.grid(axis='both', which='both', color='0.9', ls='--')
#plt.legend()
plt.show()
#bar chart 2050 and 2100 by scenario by emission source
emit_efp_2100_forbar = pd.concat([elec_emissions_cumu.loc[2100],fuel_emissions_cumu.loc[2100],process_emissions_cumu.loc[2100]],
axis=1,keys=['electricity','fuel','process'])
emit_efp_2100_mmt = emit_efp_2100_forbar/1e12
fig_cumulativeemit, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True,
gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['process'].iloc[0:5],label='process',
tick_label=scennames_labels[0:5], color='black')
ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['fuel'].iloc[0:5],label='fuel',
bottom=emit_efp_2100_mmt['process'].iloc[0:5],
tick_label=scennames_labels[0:5], color='darkred')
ax0.bar(emit_efp_2100_mmt.index[0:5], emit_efp_2100_mmt['electricity'].iloc[0:5],label='electricity',
bottom=emit_efp_2100_mmt['process'].iloc[0:5]+emit_efp_2100_mmt['fuel'].iloc[0:5],
tick_label=scennames_labels[0:5], color='blue')
ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes $CO_{2eq}$]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--')
ax0.set_axisbelow(True)
#Extreme
ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['process'].iloc[5:8],
tick_label=scennames_labels[5:8], color='black')
ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['fuel'].iloc[5:8],
bottom=emit_efp_2100_mmt['process'].iloc[5:8],
tick_label=scennames_labels[5:8], color='darkred')
ax2.bar(emit_efp_2100_mmt.index[5:8], emit_efp_2100_mmt['electricity'].iloc[5:8],
bottom=emit_efp_2100_mmt['process'].iloc[5:8]+emit_efp_2100_mmt['fuel'].iloc[5:8],
tick_label=scennames_labels[5:8], color='blue')
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--')
ax2.set_axisbelow(True)
#Ambitious
ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['process'].iloc[8:],
tick_label=scennames_labels[8:], color='black')
ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['fuel'].iloc[8:],
bottom=emit_efp_2100_mmt['process'].iloc[8:],
tick_label=scennames_labels[8:], color='darkred')
ax3.bar(emit_efp_2100_mmt.index[8:], emit_efp_2100_mmt['electricity'].iloc[8:],
bottom=emit_efp_2100_mmt['process'].iloc[8:]+emit_efp_2100_mmt['fuel'].iloc[8:],
tick_label=scennames_labels[8:], color='blue')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--')
ax3.set_axisbelow(True)
#overall fig
fig_cumulativeemit.suptitle('Cumulative Emisisons in 2100 by emission source', fontsize=24)
handles, labels = plt.gca().get_legend_handles_labels()
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.42,1))
plt.show()
#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
3 categories for this:
CEkey = ['ReMFG','Recycle_Crush','Recycled_LQ','Recycled_HQ','Resell','Repair','LQ','HQ']
CEkey_search = '|'.join(CEkey)
LinearKey = ['vMFG', 'vmfg', 'landfill']
LinearKey_search = '|'.join(LinearKey)
otherkey = ['mod_MFG','OandM','Install','Demount', 'Store'] #THIS ONE IS MISSING COLUMNS!!!
otherkey_search = '|'.join(otherkey)
scen_carbon_CE.columns
scen_carbon_linear.columns
scen_carbon_other.columns
allcolumns = list(scen_annual_carbon.columns) selectedcolumns = list(scen_carbon_other.columns)+list(scen_carbon_linear.columns)+list(scen_carbon_CE.columns) selectedcolumns
set(allcolumns).difference(selectedcolumns)
#subset by pathways
sim_carbon_CE = pd.DataFrame()
sim_carbon_linear = pd.DataFrame()
sim_carbon_necessary = pd.DataFrame()
for scen in scenarios:
scen_annual_carbon = sim_annual_carbon.filter(like=scen)
scen_carbon_CE = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(CEkey_search)]
scen_carbon_CE_sum = scen_carbon_CE.sum(axis=1)
sim_carbon_CE = pd.concat([sim_carbon_CE, scen_carbon_CE_sum], axis=1)
scen_carbon_linear = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(LinearKey_search)]
scen_carbon_linear_sum = scen_carbon_linear.sum(axis=1)
sim_carbon_linear = pd.concat([sim_carbon_linear,scen_carbon_linear_sum ], axis=1)
scen_carbon_other = scen_annual_carbon.loc[:,scen_annual_carbon.columns.str.contains(otherkey_search)]
scen_carbon_other_sum = scen_carbon_other.sum(axis=1)
sim_carbon_necessary = pd.concat([sim_carbon_necessary, scen_carbon_other_sum], axis=1)
sim_carbon_CE.columns = scennames_labels_flat
sim_carbon_linear.columns = scennames_labels_flat
sim_carbon_necessary.columns = scennames_labels_flat
#.index = pd.RangeIndex(start=2000,stop=2101,step=1)
sim_carbon_CE_cumu = sim_carbon_CE.cumsum()
sim_carbon_linear_cumu = sim_carbon_linear.cumsum()
sim_carbon_necessary_cumu = sim_carbon_necessary.cumsum()
emit_pathway = pd.concat([sim_carbon_CE_cumu.loc[2100],sim_carbon_linear_cumu.loc[2100],sim_carbon_necessary_cumu.loc[2100]],
axis=1,keys=['Circular','Linear/Virgin','Necessary'])
emit_pathway_mmt = emit_pathway/1e12
sim_carbon_CE_cumu
| PV_ICE | PERC | SHJ | TOPCon | Low Quality | Long-Lived | High Eff | Circular | High Eff + Long-life | Long-Life + Recycling | Recycled-Si + Long-life | Circular + Long-life | Circular + High Eff | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2000 | 1.243800e+08 | 1.081060e+08 | 1.038402e+08 | 1.059533e+08 | 1.243800e+08 | 1.159678e+08 | 1.034222e+08 | 1.243800e+08 | 1.034222e+08 | 1.159678e+08 | 1.243800e+08 | 1.243800e+08 | 1.243800e+08 |
| 2001 | 1.671031e+08 | 1.557593e+08 | 1.527859e+08 | 1.542588e+08 | 1.671031e+08 | 1.612394e+08 | 1.524945e+08 | 1.671031e+08 | 1.524945e+08 | 1.612394e+08 | 1.671031e+08 | 1.671031e+08 | 1.671031e+08 |
| 2002 | 2.168491e+08 | 2.022509e+08 | 1.984243e+08 | 2.003199e+08 | 2.168491e+08 | 2.093032e+08 | 1.980494e+08 | 2.168491e+08 | 1.980494e+08 | 2.093032e+08 | 2.168491e+08 | 2.168491e+08 | 2.168491e+08 |
| 2003 | 2.898076e+08 | 2.704357e+08 | 2.653579e+08 | 2.678733e+08 | 2.898039e+08 | 2.797941e+08 | 2.648604e+08 | 2.898076e+08 | 2.648604e+08 | 2.797941e+08 | 2.898076e+08 | 2.898076e+08 | 2.898076e+08 |
| 2004 | 4.327494e+08 | 4.040232e+08 | 3.964934e+08 | 4.002235e+08 | 4.327160e+08 | 4.179006e+08 | 3.957556e+08 | 4.327494e+08 | 3.957556e+08 | 4.179006e+08 | 4.327494e+08 | 4.327494e+08 | 4.327494e+08 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2096 | 9.539486e+12 | 1.137631e+15 | 1.082464e+15 | 1.105431e+15 | 2.100357e+15 | 4.351846e+10 | 4.124516e+10 | 1.457239e+15 | 4.124516e+10 | 1.552144e+14 | 8.824872e+14 | 8.160076e+14 | 9.022651e+14 |
| 2097 | 9.675062e+12 | 1.157989e+15 | 1.101828e+15 | 1.125207e+15 | 2.155752e+15 | 4.351846e+10 | 4.124516e+10 | 1.477129e+15 | 4.124516e+10 | 1.645741e+14 | 9.081595e+14 | 8.216632e+14 | 9.161259e+14 |
| 2098 | 9.822367e+12 | 1.166562e+15 | 1.109981e+15 | 1.133535e+15 | 2.211400e+15 | 4.351846e+10 | 4.124516e+10 | 1.497469e+15 | 4.124516e+10 | 1.741338e+14 | 9.347823e+14 | 8.276286e+14 | 9.303606e+14 |
| 2099 | 9.981563e+12 | 1.175323e+15 | 1.118315e+15 | 1.142046e+15 | 2.266708e+15 | 4.351846e+10 | 4.124516e+10 | 1.518299e+15 | 4.124516e+10 | 1.838479e+14 | 9.632659e+14 | 8.340084e+14 | 9.450031e+14 |
| 2100 | 1.015567e+13 | 1.184348e+15 | 1.126899e+15 | 1.150813e+15 | 2.322056e+15 | 4.351846e+10 | 4.124516e+10 | 1.539641e+15 | 4.124516e+10 | 1.936557e+14 | 9.933969e+14 | 8.551872e+14 | 9.600724e+14 |
101 rows × 13 columns
#emit_pathway.sum(axis=1) #check that matches, we're good
emit_pathway_mmt
| Circular | Linear/Virgin | Necessary | |
|---|---|---|---|
| PV_ICE | 10.155668 | 29545.307734 | 86.608227 |
| PERC | 1184.347807 | 20841.381042 | 79.515163 |
| SHJ | 1126.898709 | 19841.951078 | 75.719958 |
| TOPCon | 1150.813312 | 20260.393902 | 77.296139 |
| Low Quality | 2322.055728 | 29791.554269 | 101.376302 |
| Long-Lived | 0.043518 | 22665.530556 | 81.124405 |
| High Eff | 0.041245 | 30470.200356 | 64.810270 |
| Circular | 1539.641044 | 26384.678193 | 123.840121 |
| High Eff + Long-life | 0.041245 | 22888.315668 | 68.646302 |
| Long-Life + Recycling | 193.655661 | 22563.190574 | 81.610618 |
| Recycled-Si + Long-life | 993.396948 | 22176.873348 | 302.010424 |
| Circular + Long-life | 855.187166 | 26007.628613 | 117.086784 |
| Circular + High Eff | 960.072447 | 22427.714767 | 105.292637 |
fig_emitByPathway, (ax0,ax2,ax3) = plt.subplots(1,3,figsize=(15,8), sharey=True,
gridspec_kw={'wspace': 0, 'width_ratios': [1.5,1,1.5]})
#BAU
ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Necessary'].iloc[0:5],label='Necessary',
tick_label=scennames_labels[0:5], color='darkgray', edgecolor='black')
ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Linear/Virgin'].iloc[0:5],label='Linear/Virgin',
bottom=emit_pathway_mmt['Necessary'].iloc[0:5],
tick_label=scennames_labels[0:5], color='darkorange')
ax0.bar(emit_pathway_mmt.index[0:5], emit_pathway_mmt['Circular'].iloc[0:5],label='Circular',
bottom=emit_pathway_mmt['Necessary'].iloc[0:5]+emit_pathway_mmt['Linear/Virgin'].iloc[0:5],
tick_label=scennames_labels[0:5], color='green')
ax0.set_ylim(0,maxy+1000)
ax0.set_ylabel('Cumulative Carbon Emissions\n[million metric tonnes $CO_{2eq}$]', fontsize=20)
ax0.set_title('Baseline', fontsize=14)
ax0.set_xticklabels(labels=scennames_labels[0:5], rotation=45)
ax0.grid(axis='y', color='0.6', ls='--')
ax0.set_axisbelow(True)
#Extreme
ax2.bar(emit_pathway_mmt.index[5:8], emit_pathway_mmt['Necessary'].iloc[5:8],label='Necessary',
tick_label=scennames_labels[5:8], color='darkgray', edgecolor='black')
ax2.bar(emit_pathway_mmt.index[5:8], emit_pathway_mmt['Linear/Virgin'].iloc[5:8],label='Linear/Virgin',
bottom=emit_pathway_mmt['Necessary'].iloc[5:8],
tick_label=scennames_labels[5:8], color='darkorange')
ax2.bar(emit_pathway_mmt.index[5:8], emit_pathway_mmt['Circular'].iloc[5:8],label='Circular',
bottom=emit_pathway_mmt['Necessary'].iloc[5:8]+emit_pathway_mmt['Linear/Virgin'].iloc[5:8],
tick_label=scennames_labels[5:8], color='green')
ax2.set_title('Extreme', fontsize=14)
ax2.set_xticklabels(labels=scennames_labels[5:8], rotation=45)
ax2.grid(axis='y', color='0.6', ls='--')
ax2.set_axisbelow(True)
#Ambitious
ax3.bar(emit_pathway_mmt.index[8:], emit_pathway_mmt['Necessary'].iloc[8:],label='Necessary',
tick_label=scennames_labels[8:], color='darkgray', edgecolor='black')
ax3.bar(emit_pathway_mmt.index[8:], emit_pathway_mmt['Linear/Virgin'].iloc[8:],label='Linear/Virgin',
bottom=emit_pathway_mmt['Necessary'].iloc[8:],
tick_label=scennames_labels[8:], color='darkorange')
ax3.bar(emit_pathway_mmt.index[8:], emit_pathway_mmt['Circular'].iloc[8:],label='Circular',
bottom=emit_pathway_mmt['Necessary'].iloc[8:]+emit_pathway_mmt['Linear/Virgin'].iloc[8:],
tick_label=scennames_labels[8:], color='green')
ax3.set_title('Ambitious', fontsize=14)
ax3.set_xticklabels(labels=scennames_labels[8:], rotation=45)
ax3.grid(axis='y', color='0.6', ls='--')
ax3.set_axisbelow(True)
#overall fig
fig_emitByPathway.suptitle('Cumulative Emissions in 2100 by CE Category', fontsize=24)
handles, labels = plt.gca().get_legend_handles_labels()
plt.legend(handles[::-1], labels[::-1], bbox_to_anchor=(1.5,1))
plt.show()
#fig_eBalance.savefig('energyresults-energyBalance.png', dpi=300, bbox_inches='tight')
Trying to quantify the emissions entailed in achieving energy transition target capacities. Our current calculations don't allow a good method of CO2/kWh, but we do know how much it now takes to achieve the first 75 TW then the the next 11 TW will entail a different amount of carbon. This may be a valuable comparison
cumu_carbon_rankings_crittime#.loc[scen,2050]
| 2050 | 2100 | |
|---|---|---|
| PV_ICE | 14059.020878 | 29642.071628 |
| PERC | 12800.290860 | 22105.244013 |
| SHJ | 12193.770105 | 21044.569746 |
| TOPCon | 12448.897638 | 21488.503353 |
| Low Quality | 15169.837923 | 32214.986299 |
| Long-Lived | 13425.139177 | 22746.698479 |
| High Eff | 10927.903642 | 30535.051871 |
| Circular | 17620.780689 | 28048.159358 |
| High Eff + Long-life | 11214.153901 | 22957.003214 |
| Long-Life + Recycling | 13441.057091 | 22838.456854 |
| Recycled-Si + Long-life | 14299.423757 | 23472.280720 |
| Circular + Long-life | 18319.502170 | 26979.902562 |
| Circular + High Eff | 15083.986429 | 23493.079852 |
cumu_carbon_rankings_crittime.index = scenarios #relabel the index for the calc
scen_carbonPERcapacity = pd.DataFrame(index=scenarios)
for scen in scenarios:
#2050
scen_effectiveCap_TW = sim1.scenario[scen].dataOut_m.loc[50, 'Effective_Capacity_[W]']/1e12
scen_carbon_mmt = cumu_carbon_rankings_crittime.loc[scen,2050]
scen_carbonPERcapacity.loc[scen, 'EffectiveCap_TW_2050'] = scen_effectiveCap_TW
scen_carbonPERcapacity.loc[scen, 'Carbon_mmt_2050'] = scen_carbon_mmt
scen_carbonPERcapacity.loc[scen, 'CO2pTW_2050'] = scen_carbon_mmt/scen_effectiveCap_TW
#2100
scen_effectiveCap_TW_2100 = sim1.scenario[scen].dataOut_m.loc[100, 'Effective_Capacity_[W]']/1e12
scen_carbon_mmt_2100 = cumu_carbon_rankings_crittime.loc[scen,2100]
scen_carbonPERcapacity.loc[scen, 'EffectiveCap_TW_2100'] = scen_effectiveCap_TW_2100
scen_carbonPERcapacity.loc[scen, 'Carbon_mmt_2100'] = scen_carbon_mmt_2100
scen_carbonPERcapacity.loc[scen, 'CO2pTW_2100'] = scen_carbon_mmt_2100/scen_effectiveCap_TW_2100
#marginal increase between 2050 and 2100
round(scen_carbonPERcapacity,0)
| EffectiveCap_TW_2050 | Carbon_mmt_2050 | CO2pTW_2050 | EffectiveCap_TW_2100 | Carbon_mmt_2100 | CO2pTW_2100 | |
|---|---|---|---|---|---|---|
| PV_ICE | 75.0 | 14059.0 | 187.0 | 86.0 | 29642.0 | 345.0 |
| r_PERC | 75.0 | 12800.0 | 171.0 | 86.0 | 22105.0 | 257.0 |
| r_SHJ | 75.0 | 12194.0 | 163.0 | 86.0 | 21045.0 | 245.0 |
| r_TOPCon | 75.0 | 12449.0 | 166.0 | 86.0 | 21489.0 | 250.0 |
| r_IRENA | 75.0 | 15170.0 | 202.0 | 86.0 | 32215.0 | 375.0 |
| ex_Life | 75.0 | 13425.0 | 179.0 | 86.0 | 22747.0 | 265.0 |
| ex_High_eff | 75.0 | 10928.0 | 146.0 | 86.0 | 30535.0 | 355.0 |
| ex_Circular | 75.0 | 17621.0 | 235.0 | 86.0 | 28048.0 | 326.0 |
| h_EffLife | 75.0 | 11214.0 | 150.0 | 86.0 | 22957.0 | 267.0 |
| h_50PERC | 75.0 | 13441.0 | 179.0 | 86.0 | 22838.0 | 266.0 |
| h_RecycledPERC | 75.0 | 14299.0 | 191.0 | 86.0 | 23472.0 | 273.0 |
| h_Perovskite_life | 75.0 | 18320.0 | 244.0 | 86.0 | 26980.0 | 314.0 |
| h_Perovskite_Eff | 75.0 | 15084.0 | 201.0 | 86.0 | 23493.0 | 273.0 |